[Boto3] オプトインリージョンに作成したS3バケットにAPIアクセスする際にはリージョンを指定しなければいけない
こんにちは。サービス開発室の武田です。
ある日S3バケットにアクセスしているシステムのログに次のエラーが記録されていました。
botocore.exceptions.ClientError: An error occurred (IllegalLocationConstraintException) when calling the GetBucketLogging operation: The eu-south-1 location constraint is incompatible for the region specific endpoint this request was sent to.
見慣れないエラーですが、メッセージに出ているeu-south-1
は欧州(ミラノ)リージョンです。eu-south-1
ってそういえばオプトインリージョンだね!とすぐに気付いた方はAWSお詳しいですね!
このシステムはboto3を利用して処理をしているのですが、東京リージョンのクライアントを作成して各処理を実行していました。イメージとしては次のようなものです。
client = boto3.client("s3") result = client.get_bucket_logging(Bucket=bucket_name) print(result)
ほとんどのバケットはこの処理が動くわけですが、前述したようにオプトインリージョンのバケットを指定した場合エラーとなってしまいました。どうやらオプトインリージョンのバケットにアクセスする際には、当該リージョンのクライアントを作成する必要があるようです。
ではバケットのリージョンはどのように取得するかといえば、get_bucket_location()
を使用します。検証したところ、このメソッドはオプトインリージョンのバケットを指定しても動きました。
そんなわけで、先ほどのコードをオプトインリージョンが対象となっても動くようにするには、次のように改修すればよさそうです。
client = boto3.client("s3") try: result = client.get_bucket_logging(Bucket=bucket_name) except botocore.exceptions.ClientError as e: if e.response["Error"]["Code"] != "IllegalLocationConstraintException": raise e region = client.get_bucket_location(Bucket=bucket_name)["LocationConstraint"] optin_client = boto3.client("s3", region_name=region) result = optin_client.get_bucket_logging(Bucket=bucket_name) print(result)
まとめ
オプトインリージョンはデフォルトで有効化されているリージョンと細かい部分で差がありますね。見つけ次第細かく改善していきましょう。